package com.foreveross.proxyip.infra.base.ddd.repository;

import java.io.Serializable;
import java.util.List;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.foreveross.proxyip.infra.base.ddd.domain.IBaseEntity;
/**
 * hibernateDAO基类
 * @author xiangsf wdmz433xsf@gmail.com
 * @date 2012-10-11 下午04:55:25
 * @param <T>
 * @param <PK>
 */
@Repository("entityHibernateRepository")
public class EntityHibernateRepository implements IBaseRepository {
	/**
	 * log4j日志记录
	 */
	protected static Logger logger = Logger.getLogger(EntityHibernateRepository.class);
	
	@Inject
	@PersistenceContext(unitName="default")
	EntityManager entityManager;
	
	public EntityHibernateRepository(){
	}

	protected <T extends IBaseEntity> void evictCollection(T entity){
		if(logger.isDebugEnabled()){
//			logger.debug("执行EntityHibernateRepository里面的evictCollection");
		}
	}
	@Override
	public <T extends IBaseEntity> T get(Class<T> clazz, Serializable id) {
		return (T)entityManager.find(clazz, id);
	}
	@Override
	public <T extends IBaseEntity> T find(Class<T> clazz, Serializable id) {
		return (T)entityManager.getReference(clazz, id);
	}


	@Override
	public <T extends IBaseEntity> void create(T o) {
		entityManager.persist(o);
		this.evictCollection(o);
	}
	@Override
	public <T extends IBaseEntity> void update(T o) {
		entityManager.merge(o);
		this.evictCollection(o);
	}
	@Override
	public <T extends IBaseEntity> void delete(Class<T> clazz, Serializable id) {
		this.delete(this.get(clazz, id));
	}
	@Override
	public <T extends IBaseEntity> void delete(T o) {
		entityManager.remove(o);
		this.evictCollection(o);
	}
	@Override
	public <T extends IBaseEntity> void save(T o) {
		if (o.getId() == null) {
			this.create(o);
		} else {
			this.update(o);
		}
	}

	@Override
	public <T extends IBaseEntity> boolean exists(Class<T> clazz,
			Serializable id) {
		return this.get(clazz, id) != null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T extends IBaseEntity> List<T> findAll(Class<T> clazz) {
		String queryString = "select o from " + clazz.getName() + " as o";
		return entityManager.createQuery(queryString).getResultList();
	}
	

	/**
	 * 即时保存list
	 * @param entityList
	 */
	@Transactional
	public <T extends IBaseEntity >void transSaveList(List<T> entityList){
		for(IBaseEntity entity :entityList){
		  this.save(entity);
		}
	}
	/**
	 * 即时保存
	 * @param entityList
	 */
	@Transactional
	public synchronized <T extends IBaseEntity >void transSave(T o){
		  this.save(o);
	}
	/**
	 *  预编译hql查询
	 */
	public synchronized <T extends IBaseEntity > List<T> queryResult(final String queryStr, final Object[] params) {
		Query query = createQuery(queryStr, params);
		return query.getResultList();
	}
	
	/**
	 * 根据hql语句查询，支持分页
	 * @param queryStr
	 * @param params
	 * @param pageIndex  当前页码（从1开始）
	 * @param pageLen 每一页的长度（指每页显示多少条数据）
	 * @return
	 */
	public <T extends IBaseEntity > List<T> queryResult(final String queryStr, final Object[] params,int pageIndex,int pageLen) {
		Query query = null ;
		if(params!=null){
				query = createQuery(queryStr, params);
			}else{
				query = createQuery(queryStr);
			}
		int startIndex=(pageIndex-1)*pageLen;
		query.setFirstResult(startIndex);
		query.setMaxResults(pageLen);
		
		return query.getResultList();
	}
	

	/**
	 * 根据hql语句查询得到的结果集数量(返回long类型的数量)
	 * @param queryStr(请保证数据库语句的正确 如 select count(a) from XX a)
	 * @param params
	 * @return
	 */
	public long queryResultSize(final String queryStr, final Object[] params){
		Query query = createQuery(queryStr, params);
		return (Long)query.getSingleResult();
	}
	
	public int execute(String hql,final Object[] params) throws Exception {
		Query query = this.createQuery(hql, params);
		return query.executeUpdate();
	}
	
	private Query createQuery(String hql) {
		Query query = entityManager.createQuery(hql);
		return query;
	}
	
	
	private Query createQuery(String hql, Object[] params) {
		Query query = entityManager.createQuery(hql);
		
		return setParameters(query, params);
	}
	
	private Query setParameters(Query query, Object[] params) {
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				query.setParameter(i + 1, params[i]);
			}
		}
		return query;
	}
}
